<!-- SignaturePad.vue -->
<template>
    <div class="signature-pad" :style="wrapStyle">
        <!-- 画布容器 -->
        <div class="canvas-container" :style="canvasStyle">
            <canvas ref="canvasEl" @mousedown="startDrawing" @mousemove="draw" @mouseup="endDrawing"
                @mouseleave="endDrawing" @touchstart="startDrawing" @touchmove="draw" @touchend="endDrawing"></canvas>
        </div>

        <!-- 默认控制按钮 -->
        <div v-if="$slots.controls" class="controls-container">
            <slot name="controls" :actions="{ undo, openSettings }"></slot>
        </div>
        <div v-else class="default-controls">
            <el-button class="btn-undo" circle @click="undo">
                <el-icon>
                    <RefreshLeft />
                </el-icon>
            </el-button>
            <el-button class="btn-settings" circle @click="openSettings">
                <el-icon>
                    <Setting />
                </el-icon>
            </el-button>
        </div>

        <!-- 设置面板 -->
        <el-dialog v-model="showSettings" title="签名设置" width="90%">
            <div class="settings-panel">
                <div class="setting-item">
                    <span>笔触粗细: {{ brushSize }}px</span>
                    <vue3-slider v-model="brushSize" :min="1" :max="20" @change="updateBrush" />
                </div>
                <div class="setting-item">
                    <span>笔触颜色</span>
                    <el-color-picker v-model="brushColor" @change="updateBrush" />
                </div>
            </div>
        </el-dialog>
    </div>
</template>

<script setup>
import { RefreshLeft, Setting } from '@element-plus/icons-vue';
import { wrap } from 'lodash';
import { nextTick, onMounted, ref, watch } from 'vue';
import Vue3Slider from 'vue3-slider';

const props = defineProps({
    wrapStyle: {
        type: Object,
        default: () => ({
            width: '500px',
            height: '600px'

        }),
    },
    canvasStyle: {
        type: Object,
        default: () => ({
            border: '1px solid #ddd',
            backgroundColor: '#fff',
        }),
    },
    initialConfig: {
        type: Object,
        default: () => ({
            size: 3,
            color: '#000000',
        }),
    },
});

const emit = defineEmits(['change', 'update:config']);

// 画布实例
const canvasEl = ref(null);
let ctx = null;

// 画笔状态
const brushSize = ref(props.initialConfig.size);
const brushColor = ref(props.initialConfig.color);
const isDrawing = ref(false);
const lastPoint = ref({ x: 0, y: 0 });
const showSettings = ref(false);
const history = ref([]);

// 初始化画布
onMounted(() => {
    initCanvas();
});

const initCanvas = () => {
    const canvas = canvasEl.value;
    const dpr = window.devicePixelRatio || 1;
    const rect = canvas.getBoundingClientRect();

    canvas.width = rect.width * dpr;
    canvas.height = rect.height * dpr;
    ctx = canvas.getContext('2d');

    ctx.scale(dpr, dpr);
    ctx.lineCap = 'round';
    ctx.lineJoin = 'round';
    updateBrush();
};

// 画笔更新
const updateBrush = () => {
    ctx.lineWidth = brushSize.value;
    ctx.strokeStyle = brushColor.value;
    emit('update:config', {
        size: brushSize.value,
        color: brushColor.value,
    });
};

// 绘制逻辑
const startDrawing = (e) => {
    isDrawing.value = true;
    const pos = getPosition(e);
    lastPoint.value = pos;
    ctx.beginPath();
    ctx.moveTo(pos.x, pos.y);

    // 保存初始状态
    if (history.value.length === 0) {
        saveState();
    }
};

const draw = (e) => {
    if (!isDrawing.value) return;
    e.preventDefault();

    const pos = getPosition(e);
    ctx.lineTo(pos.x, pos.y);
    ctx.stroke();
    lastPoint.value = pos;

    // 触发变化事件
    emit('change', canvasEl.value.toDataURL());
};

const endDrawing = () => {
    isDrawing.value = false;
    saveState();
};

// 坐标获取
const getPosition = (e) => {
    const rect = canvasEl.value.getBoundingClientRect();
    const clientX = e.touches ? e.touches[0].clientX : e.clientX;
    const clientY = e.touches ? e.touches[0].clientY : e.clientY;

    return {
        x: clientX - rect.left,
        y: clientY - rect.top,
    };
};

// 历史记录
const saveState = () => {
    history.value.push(canvasEl.value.toDataURL());
};

const undo = () => {
    if (history.value.length <= 1) return clear();

    history.value.pop();
    restoreState();
};

const restoreState = async () => {
    const img = new Image();
    img.src = history.value[history.value.length - 1];

    await new Promise((resolve) => {
        img.onload = () => {
            ctx.clearRect(0, 0, canvasEl.value.width, canvasEl.value.height);
            // 保存当前ctx状态并重置变换
            ctx.save();
            ctx.setTransform(1, 0, 0, 1, 0, 0);
            ctx.drawImage(img, 0, 0);
            ctx.restore();
            resolve();
        };
    });

    emit('change', img.src);
};

const clear = () => {
    ctx.clearRect(0, 0, canvasEl.value.width, canvasEl.value.height);
    history.value = [];
    emit('change', '');
};

// 暴露方法
defineExpose({
    getSignature: () => canvasEl.value.toDataURL(),
    undo,
    clear,
    updateConfig: (config) => {
        if (config.size) brushSize.value = config.size;
        if (config.color) brushColor.value = config.color;
        updateBrush();
    },
});

// 设置面板
const openSettings = () => {
    showSettings.value = true;
};
</script>

<style scoped>
.signature-pad {
    position: relative;
}

.canvas-container {
    touch-action: none;
    width: 100%;
    height: 100%;
}

canvas {
    width: 100%;
    height: 100%;
}

.default-controls {
    position: absolute;
    bottom: 16px;
    left: 16px;
    display: flex;
    gap: 8px;
    z-index: 10;
}

.settings-panel {
    padding: 16px;

    .setting-item {
        margin-bottom: 24px;

        span {
            display: block;
            margin-bottom: 8px;
            color: #666;
        }
    }
}
</style>
